/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.search; import java.util.*; import org.openidex.search.*; import org.openide.nodes.*; /** * Task performing search. * * @author Petr Kuzel * @version 1.0 */ public class SearchTaskImpl extends SearchTask { // ScannerThread management fields /** * @associates Thread */ private Vector threads; private volatile boolean stop = false; private ThreadGroup group; // constructor fields private Node[] nodes; private SearchType[] types; private NodeAcceptor na; /** Holds all found nodes. */ private Vector found = new Vector(); private final boolean TRACE = false; /** Creates new SearchTaskImpl * @param nodes search starting points * @param types search criteria * @param na who could be notified */ public SearchTaskImpl(Node[] nodes, SearchType[] types, NodeAcceptor na) { super(org.openide.util.Task.EMPTY); group = new ThreadGroup("Search group"); // NOI18N group.setDaemon(true); group.setMaxPriority(3); threads = new Vector(); this.nodes = nodes; this.types = types; this.na = na; } /** Can be tested is finnished */ public void run() { t("run()"); // NOI18N try { // set of scanner instances to be used // more searchtypes can share one scanner instance HashMap scannerInstances = new HashMap(); if (types == null) return; // fill scanner instances for (int i = 0; i<types.length; i++) { try { Class clzz = types[i].getScannerClass(); if ( ! scannerInstances.containsKey(clzz) ) { scannerInstances.put(clzz, clzz.newInstance()); } ((Scanner) scannerInstances.get(clzz)).add(types[i]); } catch (InstantiationException ex) { // ignore such scanner } catch (IllegalAccessException ex) { // ignore such scanner } } AcceptAdapter adapter = new AcceptAdapter(na); SearchResultIntersection intersector = new SearchResultIntersection(adapter , scannerInstances.size()); Iterator it = scannerInstances.values().iterator(); while (it.hasNext()) { Scanner next = (Scanner) it.next(); t("scanner: " + next); // NOI18N ScannerThread thread = new ScannerThread(next, nodes); try { next.addScannerListener(intersector); Thread t = new Thread(group, thread, next.toString()); t.start(); threads.add(t); } catch (TooManyListenersException ex) { // ignore such scanner } } //join all scanner threads Iterator tit = threads.iterator(); while (tit.hasNext()) { Thread next = (Thread) tit.next(); try { next.join(stop ? 1:0); } catch (InterruptedException ex) { // Ok the thread is interrupted } if (next.isAlive()) { next.setPriority(1); } } } finally { notifyFinished(); notifyStop(); t("done."); // NOI18N } } /** Stop all running ScannerThreads */ public void stop() { t("stop()"); // NOI18N try { group.interrupt(); group.setMaxPriority(1); group.setDaemon(true); } catch (Exception ex) { // we are stopping threads // and no exception stop us from it } finally { notifyStop(); } } /** * Block until the search is done then return all found nodes. * @return found nodes */ public Node[] getResult() { waitStop(); return (Node[]) found.toArray(); } /** Block until search is finished. */ private synchronized void waitStop() { try { while (!stop) wait(); } catch (InterruptedException ex) { // proceed } } /** Notify that search has finished. */ private synchronized void notifyStop() { stop = true; notifyAll(); } /** One scanning thread. */ private class ScannerThread implements Runnable { private Node[] nodes; private Scanner scanner; /** * @param scanner instance that knows what to search (add(SearchType)) * @param nodes search starting pojnts */ public ScannerThread(Scanner scanner, Node[] nodes) { this.scanner = scanner; this.nodes = nodes; } public void run() { scanner.scan(nodes); } } /** Translates search events to node acceptor calls */ private class AcceptAdapter implements ScannerListener { private final NodeAcceptor acceptor; public AcceptAdapter(NodeAcceptor acceptor) { this.acceptor = acceptor; } /** Notification about new found nodes. * @throw InterruptedException to iterrupt scanner task */ public void scannerFound(ScannerEvent event) throws InterruptedException { if (stop) throw new InterruptedException(); //notify a interested acceptor if (acceptor != null) { acceptor.acceptNodes(event.getFound()); } found.addAll(Arrays.asList(event.getFound())); } } private void t(String msg) { if (TRACE) System.err.println("SearchTaskI " + msg); } } /* * Log * 7 Gandalf-post-FCS1.5.1.0 3/23/00 Petr Kuzel NullPointer bug fix. * 6 Gandalf 1.5 1/13/00 Radko Najman I18N * 5 Gandalf 1.4 1/11/00 Petr Kuzel Result details added. * 4 Gandalf 1.3 1/10/00 Petr Kuzel Buttons enabling. * 3 Gandalf 1.2 1/5/00 Petr Kuzel Margins used. Help * contexts. * 2 Gandalf 1.1 12/14/99 Petr Kuzel Minor enhancements * 1 Gandalf 1.0 12/14/99 Petr Kuzel * $ */